<template>
    <a-skeleton :animation="true" >
        <!-- 搜索框 -->
        <div class="search">
            <ComSearch @handleSearch="handleSearch" ref="comSearchRef" placeholder="搜索" :isIcon="false"/>
        </div>
        <template v-if="tabIndex === 0">
            <div class="left" ref="leftRef" v-if="filteredList(searchKey).length">
                <!-- 会话列表 -->
                <div v-for="item in filteredList(searchKey)" :key="item.id" :class="['item', { 'item-style': chatIndex === item.topicId }]" @click="handleChat(item)">
                    <div class="avatar">
                        <a-skeleton-shape shape="circle" style="width: 40px; height: 40px" v-if="loading || !chatList.length"/>
                        <template v-else>
                                <a-avatar v-if="item.messageType === 'SYSTEM_MESSAGE'">
                                    <!-- <img :src="item?.avatar || IconSystem" alt=""> -->
                                    <img :src="IconSystem" alt="">
                                </a-avatar>
                                <a-avatar :style="{ backgroundColor: '#1055bc' }" v-else>
                                    {{ item?.name?.slice(0, 1) }}
                                </a-avatar>
                                <span :class="['count flex-center', { 'style': item.unread >= 10 }]" v-if="item?.unread > 0">{{ item.unread < 100 ? item.unread : 99 }}</span>
                        </template>
                    </div>
                    <div class="label">
                        <a-skeleton-line :rows="2" :line-height="15" v-if="loading"/>
                        <template v-else>
                            <div class="name">
                                <span>{{ item.name }}</span>
                                <span class="time">{{ formatChatTime(item?.sendTime || item?.lastMsg?.sendTime) }}</span>
                            </div>
                            <div class="content">
                                <!-- 31归档 32删除 33被移除群聊 -->
                                <template v-if="useWebsocketStore().chatType.includes(item?.lastMsg?.type)">{{ item?.lastMsg?.content }}</template>
                                <template v-else>
                                    <!-- 系统消息 -->
                                    <template v-if="item.chatType === 'app'">{{ item?.lastMsg?.content }}</template>
                                    <!-- 群聊 -->
                                    <div class="content-html" v-else>
                                        <span class="aite" v-if="item.hasMentioned || item.positionId">[有人@我]</span>
                                        {{ item?.sendName ? `${item?.sendName}: ${item?.lastMsg?.content || `[${MSG_TYPE.find(child => child.value === item.lastMsg?.type)?.label}]`}` : '-' }}
                                    </div>
                                </template>
                            </div>
                        </template>
                    </div>
                </div>
            </div>
            <a-empty v-if="!loading && !filteredList(searchKey).length"></a-empty>
        </template>
        <template v-if="tabIndex === 1">
            <AddressBook ref="addressBookRef" @addressBookOperate="handleBtn('addressBookOperate', $event)"></AddressBook>
        </template>
        <!-- 底部组织选择 -->
        <div class="bottom">
            <div :class="['item', { 'style': tabIndex === item.value }]" v-for="item in tabList" :key="item.value" @click="handleBtn('tab', item.value)">
                <i :class="[`EachApp ${item.icon}`]" :style="{ fontSize: item.size + 'px' }"></i>{{ item.label }}
            </div>
        </div>
    </a-skeleton>
    <ComModal v-model:visible="modalVisible" title="新建主题会话" @handleCancel="handleBtn('close')" @handleSubmit="myComponentRef?.handleSubmit()" :disabled="!myComponentRef?.formParams?.userIds?.length">
        <component :is="myComponent" ref="myComponentRef" @handleClose="handleClose" :userList="userList" :addressBookUser="addressBookUser"></component>
    </ComModal>
</template>
<script lang="ts" setup>
const props = defineProps({
    msgType: { type: String, default: () => { return '' } }
})
import AddressBook from './AddressBook.vue';
import IconSystem from '@/assets/icon-system.png';
const AddGroup = defineAsyncComponent(() => import('./AddGroup.vue'));
import type { UserInfoEntity } from '@/entity/UserEntity';
import type { chatListEntity, chatDetailEntity } from '@/entity/im/ImEntity';
import {formatChatTime} from '@/utils';
import {MSG_TYPE} from '@/utils/filter';
import * as ApiMsg from '@/api/im';
import mitt from "@/utils/bus";
import { ImCountEnum } from '@/enums/imEnum';
const userList = ref<UserInfoEntity[]>([]); // 用户列表
const chatList = ref<chatListEntity[]>([]); // 消息列表
const chatIndex = ref(-1);
const modalVisible = ref(false);
const loading = ref(true);
const myComponent = ref(null);
const myComponentRef = ref(null);
const leftRef = ref(null);
const chatAddInfo = ref({}); // 新增群聊的信息
const searchKey = ref('');
const currentInputVal = ref(''); // 当前发送消息输入框是否有值，有值则不能上下键操控
import { useWebsocketStore } from '@/stores/modules/websocket';
import { useUserStore } from '@/stores/modules/user';
const userInfo = reactive({
	id: useUserStore().userInfo?.id
});
const router = useRouter();
const addressBookRef = ref(false);
const comSearchRef = ref(false);
const addressBookUser = ref({}); // 通讯录用户
const tabIndex = ref(0);
const tabList = reactive([
    { value: 0, icon: 'EachApp_huihua', size: 23 },
    { value: 1, icon: 'EachApp_yonghu1', size: 21 },
])

watch(() => useWebsocketStore().imStore, e => {
	userList.value = e?.userList || [];
	if(userList.value.length){
		mitt.emit('userList', userList.value);
	}
	nextTick(() => {
		chatList.value = e?.chatList || [];
	})
	const timer = setTimeout(() => {
		clearTimeout(timer);
		loading.value = false;
	}, 200);
}, { deep: true, immediate: true })

watch(() => modalVisible.value, e => {
    if(!e){
        myComponent.value = null;
    }
})

onMounted(() => {
    window.addEventListener('keydown', handleKeyDown);
})
onUnmounted(() => {
    window.removeEventListener('keydown', handleKeyDown);
    mitt.off('sendMsg', mittGetSendMsg);
    mitt.off('handlePreNext', mittHandlePreNext);
    mitt.off('inputVal', mittInputVal);
    chatList.value.forEach(item => {
        item.unread = item.unread || 0;
        item.hasMentioned = item.hasMentioned || false;
    })
});


// 搜索 0会话 1通讯录
const handleSearch = (keys: string) => {
    const bottomIndex = tabIndex.value;
    if(bottomIndex === 0){
        searchKey.value = keys;
    }else if(bottomIndex === 1){
        addressBookRef.value.pageParams.searchKey = keys;
    }
}

// 计算过滤后的数据
const filteredList = computed(() => (keys: string) => {
    const query = keys?.trim().toLowerCase();
    const list: chatListEntity[] = query ? chatList.value.filter(item => item.name?.trim().toLowerCase().includes(query)) : chatList.value;
    function isGroupMsg(item: string | undefined){
        return item === 'GROUP_MESSAGE';
    }
    const msgType = props.msgType ? +props.msgType : '';
    if(msgType === ImCountEnum.UnRead){ // 未读
        return list.filter(item => item.unread > 0 || item.unread === null);
    }else if(msgType === ImCountEnum.Mention){ // @我
        return list.filter(item => isGroupMsg(item.messageType) && (item.hasMentioned || item.hasMentioned === null));
    }else if(msgType === ImCountEnum.Create){ // 召集
        return list.filter(item => isGroupMsg(item.messageType) && item.creatorId === userInfo.id);
    }else if(msgType === ImCountEnum.Join){ // 参与
        return list.filter(item => isGroupMsg(item.messageType) && item.creatorId !== userInfo.id);
    }else if(msgType === ImCountEnum.Archive){ // 归档
        return list.filter(item => isGroupMsg(item.messageType) && item.status === 1);
    }
    return list;
});

// tab底部切换
const handleBtn = async (type: string, val: number) => {
    if(type === 'tab'){
        if(tabIndex.value === val) return;
        tabIndex.value = val;
        searchKey.value = '';
        comSearchRef.value.searchKey = '';
    }else if(type === 'addressBookOperate'){
        await handleAdd();
        addressBookUser.value = val;
    }else if(type === 'close'){
        modalVisible.value = false;
        addressBookUser.value = {};
    }
}

// 切换群聊
const handleChat = async (row: chatDetailEntity) => {
    console.log('切换===', chatIndex.value, {...row});
    if(chatIndex.value === row.topicId && !row.unread) return;
    const rows = JSON.parse(JSON.stringify(row));
    chatIndex.value = row.topicId;
    mitt.emit('handleChat', { ...rows, isDetail: true, isOther: true, msgType: props.msgType });
    chatList.value.map((item: chatDetailEntity) => {
        if(item.topicId === chatIndex.value){
            if(item.lastMsg){
                item.lastMsg.mentionedIds = [];
            }
            item.hasMentioned = +props.msgType === ImCountEnum.Mention ? null : false;
            item.positionId = null;
            item.unread = props.msgType === 'unread' ? null : 0;
            item.isRead = true;
        }
        return item;
    })
}

// 新增
const handleAdd = () => {
    myComponent.value = AddGroup;
    modalVisible.value = true;
}

// 关闭modal
const handleClose = (value) => {
    modalVisible.value = false;
    chatAddInfo.value = {...value};
    tabIndex.value = 0;
    router.push('/im');
    console.log('添加===', value.topicId, value);
}

// 根据接收不同消息分类处理
const mittGetSendMsg = (value) => {
    console.log('接收消息===左', {...value});
    const { sendId, sendName, sendTime, sendType = 'GROUP_MESSAGE', content, topicId, type, mentionedIds } = value;
    // 本条消息是否是本人发送
    const isMySelf = userInfo.id === sendId;
    // SYSTEM_MESSAGE
    if(sendType === 'GROUP_MESSAGE'){
        let targetItem = chatList.value.find(item => item.topicId === topicId);
        const name = targetItem?.name || chatAddInfo.value?.name;
        if(targetItem){ // 这里处理已有的群
            targetItem = {
                ...targetItem,
                sendTime,
                messageType: sendType,
                lastMsg: { ...value }
            };
            targetItem.lastMsg.content = content?.replace(/<p>/g, '').replace(/<\/p>/g, ' ').replace(/\s+/g,' ');
            if(targetItem.lastMsg.content?.includes('<img')){
                targetItem.lastMsg.content = targetItem.lastMsg.content?.replace(/<img.*?>/g, "[图片]");
            }
            targetItem.lastMsg.content = targetItem.lastMsg.content?.replace(/<[^>]*>/g,' ');
            // 处理文档、视频、音频、图片等等类型
            // const url = targetItem.lastMsg?.extraInfo?.url;
            // if(url){
            //     targetItem.lastMsg.content = `[${MSG_TYPE.find(child => child.value === type)?.label}]`;
            // }
            // console.log('已有===', {...targetItem});
           if(type === 31){ // 归档
                console.log('群聊已被归档====');
                const tips = { btnType: 'return', btnTips: content, isDetail: true };
                targetItem.unread = targetItem.topicId === chatIndex.value ? 0 : (targetItem.unread || 0);
                const targetIndex = chatList.value.findIndex(item => item.topicId === topicId);
                chatList.value.splice(targetIndex, 1);
                chatList.value.unshift(targetItem);
                // 如果归档时，当前正处于当前群聊时, 重新获取详情
                if(chatIndex.value === topicId){
                    mitt.emit('handleChat', {...targetItem, ...tips});
                }
            }else if(type === 32){ // 删除
                const tips = { btnType: 'del', btnTips: content };
                // 是群主则直接删除当前群聊，否则展示删除相关信息
                console.log('群聊已被删除====');
                const targetIndex = chatList.value.findIndex(item => item.topicId === topicId);
                chatList.value.splice(targetIndex, 1);
                mitt.emit('handleChat', {...targetItem, ...tips, isEmpty: true});
            }else if(type === 33){ // 移除群聊
                console.log('移出群聊===');
                const tips = { btnType: 'remove', btnTips: content };
                const params = {
                    ...tips,
                    ...targetItem,
                    // unread: 0,
                }
                const targetIndex = chatList.value.findIndex(item => item.topicId === topicId);
                // 从数组中移除该项
                chatList.value.splice(targetIndex, 1);
                chatList.value.unshift(params);
                if(chatIndex.value === topicId){
                    mitt.emit('handleChat', {...targetItem, ...tips });
                }
            }else if(type === 21){ // 文字提示(移除、拉人、归档等等)
                const tips = { btnType: 'add', btnTips: content };
                targetItem.name = name;
                targetItem.sendName = sendName;
                // targetItem.unread = isMySelf ? targetItem.unread : targetItem.unread + 1;
                const targetIndex = chatList.value.findIndex(item => item.topicId === topicId);
                // console.log('文字提示===', isMySelf, {...targetItem});
                chatList.value.splice(targetIndex, 1);
                chatList.value.unshift(targetItem);
                if(chatIndex.value === topicId){
                    mitt.emit('handleChat', {...targetItem, ...tips });
                }
            }else{ // 文字消息
                // console.log('文字消息-====', targetItem.unread);
                targetItem.name = name;
                targetItem.sendName = sendName;
                // 判断@数组里是否有自己
                const isMe = [userInfo.id, 0].some(item => mentionedIds?.includes(item));
                if(isMe){
                    targetItem.lastMsg.mentionedIds = [mentionedIds?.includes(0) ? 0 : userInfo.id];
                    // @我的消息id 如果没有则赋值，反之则拿id作为第一次@我的消息id
                    targetItem.hasMentioned = targetItem.lastMsg.mentionedIds?.length > 0 || targetItem.hasMentioned;
                    targetItem.positionId = targetItem.positionId || value.id;
                }
                // targetItem.unread = isMySelf ? 0 : (targetItem.unread || 0) + 1; // 发送消息当前人不做未读数+1，其他人+1
                const targetIndex = chatList.value.findIndex(item => item.topicId === topicId);
                chatList.value.splice(targetIndex, 1);
                chatList.value.unshift(targetItem);
            }
        }else{ // 这里处理新建的群，创建者第一次发消息，其他用户需要把此群添加进去，第二次发消息就不会走这里了
            if(type !== 32){
                ApiMsg.ApiChatListDetail(topicId).then((res) => {
                    const params = {
                        ...chatAddInfo.value,
                        topicId,
                        name: res.name,
                        sendTime,
                        content: content?.replace(/<p>/g, '').replace(/<\/p>/g, ' ').replace(/\s+/g,' '),
                        isDetail: isMySelf,
                        chatType: 'chat',
                        btnType: 'add',
                        isFirst: true,
                        messageType: sendType,
                        unread: isMySelf ? 0 : 1,
                        lastMsg: {
                            ...value,
                        }
                    }
                    // console.log('未有===', {...params});
                    if(useWebsocketStore().chatType.includes(type)){
                        chatList.value.unshift(params);
                        // 如果是群主则进入新建群的详情
                        if(isMySelf){
                            chatIndex.value = topicId;
                            mitt.emit('handleChat', params);
                        }
                    }
                }).catch((err) => {
                    console.log(err);
                });
            }
        }
        // console.log('chatList.value===', JSON.parse(JSON.stringify(chatList.value)));
    }else if(sendType === 'del'){
        chatList.value = chatList.value.filter(item => item.topicId !== value.topicId);
    }else if(sendType === 'read'){
        chatList.value.map(item => {
            if(item.topicId === topicId){
                item.hasMentioned = +props.msgType === ImCountEnum.Mention ? null : false;
                item.positionId = null;
                item.unread = props.msgType ? null : 0;
            }
            return item;
        })
    }else if(sendType === 'SYSTEM_MESSAGE'){ // 系统消息
        const items = chatList.value.find(item => item.messageType === sendType);
        console.log('系统消息===', chatList.value, items);
        const targetItem = {
            ...items,
            id: value.id,
            sendTime,
            name: '系统通知',
            chatType: 'app',
            avatar: IconSystem,
            messageType: sendType,
            unread: items ? ++items.unread : 1,
            lastMsg: { ...value, content: value.title }
        };
        if(!items){
            chatList.value.unshift(targetItem);
        }else{
            const targetIndex = chatList.value.findIndex(item => item.messageType === sendType);
            // console.log('targetIndex===', targetIndex, targetItem);
            chatList.value.splice(targetIndex, 1);
            chatList.value.unshift(targetItem);
            if(chatIndex.value === items?.topicId){
                mitt.emit('handleChat', { ...targetItem, isCurrent: true });
            }
        }
    }
    if(leftRef.value){
        leftRef.value.scrollTop = 0;
    }
}

// 上下键切换群聊
const mittHandlePreNext = ({ preNext, topicId }) => {
    let index = chatList.value.findIndex(item => item.topicId === topicId);
    if(preNext === 'pre'){ // 上
        index = index === 0 ? chatList.value.length - 1 : index - 1;
    }else if(preNext === 'next'){ // 下
        index = index === chatList.value.length - 1 ? 0 : index + 1;
    }
    handleChat(chatList.value[index]);
}

// 接收发送消息输入框的值
const mittInputVal = (value) => {
    currentInputVal.value = value;
}

mitt.on('sendMsg', mittGetSendMsg);
mitt.on('handlePreNext', mittHandlePreNext);
mitt.on('inputVal', mittInputVal);

// 上下键切换群聊-处理不在输入框的情况(比如: 系统消息等)
const handleKeyDown = (event) => {
	return;
    // 当前处于系统消息时或者按上下键都可
    // console.log('键盘===', chatIndex.value >= 0, [38, 40].includes(event.keyCode), !currentInputVal.value);
    if(chatIndex.value >= 0 && [38, 40].includes(event.keyCode) && !currentInputVal.value){
        let index = chatList.value.findIndex(item => item.topicId === chatIndex.value);
        if(event.keyCode === 38){ // 上
            index = index === 0 ? chatList.value.length - 1 : index - 1;
        }else if(event.keyCode === 40){ // 下
            index = index === chatList.value.length - 1 ? 0 : index + 1;
        }
        handleChat(chatList.value[index]);
        currentInputVal.value = '';
    }
}

defineExpose({
    searchKey,
    handleAdd
})
</script>
<style lang="scss" scoped>
.arco-skeleton{
    display: flex;
    flex-direction: column;
    background: white;
    border-right: 1px solid #eee;
    position: relative;
    // padding: 10px;
    .search{
        padding: 14px 10px 14px 10px;
        display: flex;
        align-items: center;
        .search-box{
            width: 100%;
        }
        :deep(.arco-input-wrapper){
            background-color: white !important;
        }
    }
    .left{
        height: calc(100% - 115px);
        width: 100%;
        overflow-y: auto;
        overflow-x: hidden;
        padding: 0 !important;
        .item{
            display: flex;
            align-items: center;
            padding: 12px;
            position: relative;
            margin: 0 10px;
            border-radius: 4px;
            &:not(:last-child){
                margin-bottom: 8px;
            }
            &:hover{
                cursor: pointer;
                background: #f5f7fa;
            }
            &-style{
                background: #f0f2f5;
                cursor: pointer;
                &:hover{
                    background: #f0f2f5;
                }
            }
            .avatar{
                position: relative;
                .img{
                    width: 40px;
                    height: 40px;
                    border-radius: 50%;
                }
                .count{
                    position: absolute;
                    right: -6px;
                    top: -6px;
                    z-index: 2;
                    background: #f95557;
                    color: white;
                    width: 18px;
                    height: 18px;
                    border-radius: 50%;
                    justify-content: space-around;
                    font-weight: 600;
                    &.style{
                        font-size: 11px;
                    }
                }
                &-default{
                    font-size: 20px;
                    font-weight: bold;
                    justify-content: space-around;
                    background-color: rgb(201, 180, 85);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    border-radius: 50%;
                    width: 40px;
                    height: 40px;
                    color: white;
                    font-size: 15px;
                    font-weight: normal;
                }
            }
            .msg{
                font-size: 30px;
                color: #ebe772;
                margin: 0 8px 0 12px;
            }

            .label{
                padding-left: 15px;
                color: #999;
                width: 100%;
                flex: 1;
                overflow: hidden;
                .name{
                    font-size: 15px;
                    font-weight: 500;
                    margin-bottom: 8px;
                    color: #333;
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                }
                .content{
                    overflow: hidden;
                    text-overflow: ellipsis;
                    display: -webkit-box;
                    -webkit-line-clamp: 1;
                    /* autoprefixer: ignore next */
                    -webkit-box-orient: vertical;
                    /* autoprefixer: on */
                    word-wrap: break-word;
                    &-html{
                        white-space: nowrap;
                        overflow: hidden;
                        text-overflow: ellipsis;
                        .aite{
                            color: red;
                        }
                    }
                }
                .time{
                    font-weight: normal;
                    font-size: 12px;
                    color: #999;
                }
            }
        }
    }
    .bottom{
        position: absolute;
        left: 0;
        bottom: 0;
        width: 100%;
        height: 55px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-top: 1px solid #eee;
        column-gap: 10px;
        z-index: 9;
        background: white;
        .item{
            font-size: 15px;
            cursor: pointer;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #999;
            padding: 0 20px;
            i{
                margin-right: 5px;
            }
            &.style{
                color: var(--green);
            }
        }
    }

}
</style>
